package com.afei.tajweed;

import com.afei.oid.EbookConstants;
import com.afei.oid.FactoryClass;
import com.afei.oid.GetPlayInfo;
import com.afei.oid.SentenceInfo;
import com.afei.oid.TheardProxy;
import com.afei.oid.ToastMy;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

public class MuPDFReaderView extends ReaderView {
	enum Mode {Viewing, Selecting, Drawing}
	private static final int NARRATIONMAGIN = 10;
	private final Context mContext;
	private boolean mLinksEnabled = false;
	private Mode mMode = Mode.Viewing;
	private boolean tapDisabled = false;
	private int tapPageMargin;
	public static ToastMy 		 mNarrationToast;
	private SentenceInfo mCurrentSentence;
	private UiHandler mUiHandler;
	private TheardProxy mTheardProxy;
	private GetPlayInfo mGetPlayInfo = null;
	protected void onTapMainDocArea(MotionEvent e) {}
	protected void onHideTopBar(boolean enable) {}
	protected void onDocMotion() {}
	protected void onHit(Hit item) {};
	protected void onTouch(MotionEvent e,Rect rect){};
	protected boolean EnableShowNarration(){
		return true;};

	public void setLinksEnabled(boolean b) {
		mLinksEnabled = b;
		resetupChildren();
	}

	public void setMode(Mode m) {
		mMode = m;
	}

	public MuPDFReaderView(Activity act,MuPDFCore core,String filename) {
		super(act);
		mContext = act;
		mNarrationToast = new ToastMy(act);
		mUiHandler = new UiHandler();
		mTheardProxy = new TheardProxy(act,filename,core.GetMp3Offset(),mUiHandler);
		mGetPlayInfo = FactoryClass.FactoryGetPlayInfo();
		// Get the screen size etc to customise tap margins.
		// We calculate the size of 1 inch of the screen for tapping.
		// On some devices the dpi values returned are wrong, so we
		// sanity check it: we first restrict it so that we are never
		// less than 100 pixels (the smallest Android device screen
		// dimension I've seen is 480 pixels or so). Then we check
		// to ensure we are never more than 1/5 of the screen width.
		DisplayMetrics dm = new DisplayMetrics();
		act.getWindowManager().getDefaultDisplay().getMetrics(dm);
		tapPageMargin = (int)dm.xdpi;
		if (tapPageMargin < 100)
			tapPageMargin = 100;
		if (tapPageMargin > dm.widthPixels/5)
			tapPageMargin = dm.widthPixels/5;
	}
	class UiHandler extends Handler{

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			EbookConstants.UIEvent uievent = EbookConstants.UIEvent.values()[msg.what];
			MuPDFView pageView = (MuPDFView) getDisplayedView();
			switch(uievent)
			{
			case UIEVENT_PLAYEND:
				if(mNarrationToast != null)
				{
					mNarrationToast.cancelCurrentToast();
					if(pageView != null)
						pageView.SetHitRect(null);
				}
				break;
			case UIEVENT_MOVENEXTPAGE:
				if(pageView != null)
					pageView.SetHitRect(null);
				setDisplayedViewIndex(msg.arg1 - 1);
				break;
			case UIEVENT_SHOWNARRATION:
				if(pageView != null && (msg.arg2 & 0x8000) != 0)
					pageView.MakeHitRect(msg.arg2 & 0x7fff);
				ShowNarration((SentenceInfo)msg.obj,msg.arg1);
				break;
			default:
				break;
			}
			super.handleMessage(msg);
		}
		
	}
	private void ShowNarration(SentenceInfo sentence,int mp3times)
	{
		  if(sentence != null && EnableShowNarration())
		  {
			  mNarrationToast.cancelCurrentToast();
			  mNarrationToast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,0,NARRATIONMAGIN);// | Gravity.FILL_HORIZONTAL
			  mNarrationToast.showMessage(sentence.mNarration,mp3times); 
		  }
	}
//	private void ShowNarration()
//	{	  
//		MuPDFView pageView = (MuPDFView) getDisplayedView();
//		  int ypos = 0,viewtop = 0;
//		  mNarrationToast.cancelCurrentToast();
//		  mNarrationToast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,0,NARRATIONMAGIN);// | Gravity.FILL_HORIZONTAL
//		  EbookConstants.SentenceType type = EbookConstants.SentenceType.values()[mCurrentSentence.mType];
//		  if(mCurrentSentence != null && (type == EbookConstants.SentenceType.TYPE_NEWSENTENCE
//				  || type == EbookConstants.SentenceType.TYPE_SENTENCE))
//		  {
//			  mNarrationToast.showMessage(mCurrentSentence.mNarration,10*1000); 
//		  }
//	}
	public boolean onSingleTapUp(MotionEvent e) {
		LinkInfo link = null;

		if (mMode == Mode.Viewing && !tapDisabled) {
			MuPDFView pageView = (MuPDFView) getDisplayedView();
			Hit item = pageView.passClickEvent(e.getX(), e.getY());
			onHit(item);
			if (item == Hit.Nothing) 
			{
				if (mLinksEnabled && pageView != null
				&& (link = pageView.hitLink(e.getX(), e.getY())) != null) {
					link.acceptVisitor(new LinkInfoVisitor() {
						@Override
						public void visitInternal(LinkInfoInternal li) {
							// Clicked on an internal (GoTo) link
							setDisplayedViewIndex(li.pageNumber);
						}

						@Override
						public void visitExternal(LinkInfoExternal li) {
							Intent intent = new Intent(Intent.ACTION_VIEW, Uri
									.parse(li.url));
							mContext.startActivity(intent);
						}

						@Override
						public void visitRemote(LinkInfoRemote li) {
							// Clicked on a remote (GoToR) link
						}
					});
				}
//				else if (e.getX() < tapPageMargin) 
//				{
//					super.smartMoveBackwards();
//				}
//				else if (e.getX() > super.getWidth() - tapPageMargin) 
//				{
//					super.smartMoveForwards();
//				} 
//				else if (e.getY() < tapPageMargin) 
//				{
//					super.smartMoveBackwards();
//				} 
//				else if (e.getY() > super.getHeight() - tapPageMargin)
//				{
//					super.smartMoveForwards();
//				}
//				else 
				{
					onTapMainDocArea(e);
				}
			}
			else if(item == Hit.Mp3)
			{
				onHideTopBar(true);
				mCurrentSentence = mGetPlayInfo.GetCurrentSentence(pageView.GetHitSentenceIndex());
				if(mCurrentSentence != null)
				{
					mTheardProxy.SendPlayAudio(pageView.GetHitSentenceIndex());
				}
			}
		}
		return super.onSingleTapUp(e);
	}
	public void OnStop()
	{
		mTheardProxy.StopPlayAudio();
	}
	public void OnClose()
	{
		mTheardProxy.SendPlayAudio(-1);
	}
	public void OnAutoEvent(EbookConstants.TouchEvent event)
	{
		mTheardProxy.SendAutoEvent(event);
	}
	private void OnOidTouch(MotionEvent e)
	{
		PageView pageView = (PageView)getDisplayedView();
		Rect viewArea = new Rect();
		viewArea.left = pageView.getLeft();
		viewArea.top = pageView.getTop();
		viewArea.bottom = pageView.getBottom();
		viewArea.right = pageView.getRight();
		onTouch(e,viewArea);
	}
	@Override
	public boolean onDown(MotionEvent e) {

		return super.onDown(e);
	}

	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		MuPDFView pageView = (MuPDFView)getDisplayedView();
		switch (mMode) {
		case Viewing:
			if (!tapDisabled)
				onDocMotion();

			return super.onScroll(e1, e2, distanceX, distanceY);
		case Selecting:
			if (pageView != null)
				pageView.selectText(e1.getX(), e1.getY(), e2.getX(), e2.getY());
			return true;
		default:
			return true;
		}
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		switch (mMode) {
		case Viewing:
			return super.onFling(e1, e2, velocityX, velocityY);
		default:
			return true;
		}
	}

	public boolean onScaleBegin(ScaleGestureDetector d) {
		// Disabled showing the buttons until next touch.
		// Not sure why this is needed, but without it
		// pinch zoom can make the buttons appear
		tapDisabled = true;
		return super.onScaleBegin(d);
	}

	public boolean onTouchEvent(MotionEvent event) {

		if ( mMode == Mode.Drawing )
		{
			float x = event.getX();
			float y = event.getY();
			switch (event.getAction())
			{
				case MotionEvent.ACTION_DOWN:
					touch_start(x, y);
					break;
				case MotionEvent.ACTION_MOVE:
					touch_move(x, y);
					break;
				case MotionEvent.ACTION_UP:
					touch_up();
					break;
			}
		}

		if ((event.getAction() & event.getActionMasked()) == MotionEvent.ACTION_DOWN)
		{
			tapDisabled = false;
		}

		return super.onTouchEvent(event);
	}

	private float mX, mY;

	private static final float TOUCH_TOLERANCE = 2;

	private void touch_start(float x, float y) {

		MuPDFView pageView = (MuPDFView)getDisplayedView();
		if (pageView != null)
		{
			pageView.startDraw(x, y);
		}
		mX = x;
		mY = y;
	}

	private void touch_move(float x, float y) {

		float dx = Math.abs(x - mX);
		float dy = Math.abs(y - mY);
		if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
		{
			MuPDFView pageView = (MuPDFView)getDisplayedView();
			if (pageView != null)
			{
				pageView.continueDraw(x, y);
			}
			mX = x;
			mY = y;
		}
	}

	private void touch_up() {

		// NOOP
	}

	protected void onChildSetup(int i, View v) {
		if (SearchTaskResult.get() != null
				&& SearchTaskResult.get().pageNumber == i)
			((MuPDFView) v).setSearchBoxes(SearchTaskResult.get().searchBoxes);
		else
			((MuPDFView) v).setSearchBoxes(null);

		((MuPDFView) v).setLinkHighlighting(mLinksEnabled);

		((MuPDFView) v).setChangeReporter(new Runnable() {
			public void run() {
				applyToChildren(new ReaderView.ViewMapper() {
					@Override
					void applyToView(View view) {
						((MuPDFView) view).update();
					}
				});
			}
		});
	}

	protected void onMoveToChild(int i) {
		if (SearchTaskResult.get() != null
				&& SearchTaskResult.get().pageNumber != i) {
			SearchTaskResult.set(null);
			resetupChildren();
		}
		FactoryClass.FactoryGetPlayInfo().GetPageSentence(i + 1);
	}

	@Override
	protected void onMoveOffChild(int i) {
		View v = getView(i);
		if (v != null)
		{
			((MuPDFView)v).deselectAnnotation();
			((MuPDFView)v).SetHitRect(null);
		}
		if(mNarrationToast != null)
			mNarrationToast.cancelCurrentToast();
	}

	protected void onSettle(View v) {
		// When the layout has settled ask the page to render
		// in HQ
		((MuPDFView) v).addHq(false);
	}

	protected void onUnsettle(View v) {
		// When something changes making the previous settled view
		// no longer appropriate, tell the page to remove HQ
		((MuPDFView) v).removeHq();
	}

	@Override
	protected void onNotInUse(View v) {
		((MuPDFView) v).releaseResources();
	}

	@Override
	protected void onScaleChild(View v, Float scale) {
		((MuPDFView) v).setScale(scale);
	}
}
